package org.apache.commons.graph /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * The `MutableGraph` is a graph that supports the addition and removal of vertex and edges.
 *
 * @param <V> the Graph vertices type
 * @param <E> the Graph edges type
</E></V> */
interface MutableGraph<V, E> : Graph<V, E> {
    /**
     * Adds a feature to the edge attribute of the `MutableGraph` object
     *
     * **NOTE**: implementors have to take in consideration throwing a [GraphException]
     * if an error occurs while performing that operation.
     *
     * @param head the head vertex
     * @param e the edge has to be added in this `MutableGraph` instance.
     * @param tail the tail vertex
     */
    fun addEdge(head: V, e: E, tail: V)

    /**
     * Adds a feature to the vertex attribute of the `MutableGraph` object.
     *
     * **NOTE**: implementors have to take in consideration throwing a [GraphException]
     * if an error occurs while performing that operation.
     *
     * @param v the vertex has to be added in this `MutableGraph` instance.
     */
    fun addVertex(v: V)

    /**
     * Removed the edge from the `MutableGraph` object.
     *
     * **NOTE**: implementors have to take in consideration throwing a [GraphException]
     * if an error occurs while performing that operation.
     *
     * @param e the edge has to be removed from this `MutableGraph` instance.
     */
    fun removeEdge(e: E)

    /**
     * Removes the vertex from the `MutableGraph` object.
     *
     * **NOTE**: implementors have to take in consideration throwing a [GraphException]
     * if an error occurs while performing that operation.
     *
     * @param v the vertex has to be removed from this `MutableGraph` instance.
     */
    fun removeVertex(v: V)

    infix  fun<N : V,N2 : V,A : E> Pair<N,N2>.edge(arc:A) = addEdge(first,arc,second)

    infix  fun<N : V,N2 : V,A : E> A.on(ab:Pair<N,N2>) = addEdge(ab.first,this, ab.second)

    fun<N : V> N.add():N = apply(::addVertex)

    fun<N : V> N.addOrGet():N = apply{
        if(!containsVertex(this))
            addVertex(this)
    }

    fun<N : V> N.addOrRemoveFirst():N = apply{
        if(containsVertex(this))
            removeVertex(this)
        addVertex(this)
    }

//    fun V.removeSelf() = let(::removeVertex)
//
//    fun E.removeSelf() = let(::removeEdge)

    fun addAllVertex(vararg v: V) = v.forEach(::addVertex)

}
